pub mod api;
pub mod container;
pub mod core;

use crate::components::{
    DropdownItem, DropdownList, EditorApi, EditorCore, EditorCoreSelection, NodeListHelper,
    OutlineApi,
};
use crate::errors::{log_error, MyError, MyResult};
use crate::models::Note;
use crate::styles::{ElementStyle, StyleItem};
use gloo::console::log;
use lazy_static::lazy_static;
use wasm_bindgen::JsCast;
use web_sys::Node;
use yew::{platform::spawn_local, prelude::*};

const EDITOR_CONTAINER_STYLE: &str = r#"height: 100%;"#;

lazy_static! {
    static ref KEY_LIST: Vec<DropdownItem> = vec![
        DropdownItem {
            key: StyleItem::Title1,
            title: String::from("标题1"),
        },
        DropdownItem {
            key: StyleItem::Title2,
            title: String::from("标题2"),
        },
        DropdownItem {
            key: StyleItem::Title3,
            title: String::from("标题3"),
        },
        DropdownItem {
            key: StyleItem::Normal,
            title: String::from("正文"),
        }
    ];
}

#[derive(Properties, PartialEq)]
pub struct EditorProps {
    #[prop_or_default]
    pub on_save: Callback<Note>,
    #[prop_or_default]
    pub data: Note,
}

pub enum Msg {
    ApplyStyle(usize),
    SelectionChanged(Option<EditorCoreSelection>),
}
pub struct Editor {
    current_selection: Option<EditorCoreSelection>,
}

async fn update_title(selection: Option<&EditorCoreSelection>) {
    if let Some(selection1) = selection {
        if let Some(focus_node) = &selection1.focus_node {
            if let Some(first_node) = EditorApi::editor_node().child_nodes().first_child() {
                if first_node.contains(Some(focus_node)) {
                    EditorApi::set_editor_title(
                        EditorApi::editor_title().as_ref().map(|e| e.as_str()),
                    );
                }
            }
        }
    }
}

async fn set_outline(selection: Option<EditorCoreSelection>) -> MyResult<()> {
    if let Some(node_selection) = selection {
        if !EditorApi::is_text_node(node_selection.focus_node.as_ref()) {
            return Ok(());
        }
        let focus_node = node_selection.focus_node.unwrap();
        let parent_focus_node = focus_node.parent_node();
        if OutlineApi::is_outline(parent_focus_node.as_ref()) {
            // 已经是outline类型的节点，所以不用处理
            return Ok(());
        }

        let text = &focus_node.text_content().unwrap_or_default();
        if EditorApi::is_top_level_node(parent_focus_node.as_ref())
            && OutlineApi::is_outline_tag(text)
        {
            OutlineApi::build_outline(parent_focus_node.as_ref(), text);
            return Ok(());
        }
    }
    log!("not found");

    Ok(())
}

impl Component for Editor {
    type Message = Msg;
    type Properties = EditorProps;
    fn create(_ctx: &Context<Self>) -> Self {
        Self {
            current_selection: None,
        }
    }
    fn update(&mut self, _ctx: &Context<Self>, msg: Self::Message) -> bool {
        match msg {
            Msg::ApplyStyle(index) => {
                if let Some(editor_selection) = &self.current_selection {
                    ElementStyle::Title(&KEY_LIST[index].key).apply(editor_selection);
                    self.current_selection = None;
                }
            }
            Msg::SelectionChanged(selection) => {
                {
                    let selection = selection.clone();
                    spawn_local(async move {
                        update_title(selection.as_ref()).await;
                        log_error(set_outline(selection).await, None);
                    });
                }
                self.current_selection = selection;
            }
        };
        false
    }

    fn view(&self, ctx: &Context<Self>) -> Html {
        html! {
            <div style={EDITOR_CONTAINER_STYLE} class={classes!("column")}>
                <div class={classes!("section", "column", "v-small-margin", "flex-grow")}>
                    <div>
                        <span>{"标题:"}</span><span id={EditorApi::editor_title_id()}></span>
                    </div>
                    <div class={classes!("row",
                        "section",
                        "w-100",
                        "v-small-padding",
                        "h-small-padding")}
                        style={"z-index:99"}
                    > // 工具条
                        <DropdownList
                            text="大纲"
                            key_list={KEY_LIST.clone()}
                            select_key={ctx.link().callback(Msg::ApplyStyle)}
                        />
                    </div>// 工具条
                    <div class={classes!("column", "flex-grow", "pos-relative", "overflow-scroll")}>
                        <EditorCore selection_changed={ctx.link().callback(Msg::SelectionChanged)}/>
                    </div>
                </div>
            </div>
        }
    }
}
// onfocus={ctx.link().callback(|e| Msg::Focused)}
